﻿using DAL;
using IBLL;
using IDAL;
using Models;
using Models.DTO;
using Models.Enums;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace BLL
{
    public class CommodityInfoBLL : ICommodityInfoBLL
    {
        #region 构造函数
        private ICommodityInfoDAL _commodityInfoDAL;
        private UnmanContexts _unmanContexts;   //数据上下文
        private IUserBalanceInfoDAL _userBalanceInfoDAL;    //用户余额表
        private IOrderInfoDAL _orderInfoDAL;          //订单表



        public CommodityInfoBLL(
            UnmanContexts unmanContexts
            , ICommodityInfoDAL commodityInfoDAL
            , IUserBalanceInfoDAL userBalanceInfoDAL
            , IOrderInfoDAL orderInfoDAL
            )
        {
            _unmanContexts = unmanContexts;
            _commodityInfoDAL = commodityInfoDAL;
            _userBalanceInfoDAL = userBalanceInfoDAL;
            _orderInfoDAL = orderInfoDAL;
        }
        #endregion

        #region 新增(CreateCommodityInfo)
        public bool CreateCommodityInfo(CommodityInfo commodityInfo, out string msg)
        {

            //非空判断
            if (string.IsNullOrWhiteSpace(commodityInfo.CommodityName))
            {
                msg = "商品名称不能为空";
                return false;
            }
            //查询判断是否重复
            CommodityInfo oldEntity = _commodityInfoDAL.GetEntities().FirstOrDefault(c => c.CommodityName == commodityInfo.CommodityName);
            if (oldEntity != null)
            {
                msg = "已存在";
                return false;
            }
            //给对象补全属性
            commodityInfo.Id = Guid.NewGuid().ToString();
            commodityInfo.CreateTime = DateTime.Now;
            //提交到数据库
            bool isSuccess = _commodityInfoDAL.CreateEntity(commodityInfo);
            //返回结果
            msg = isSuccess ? "添加成功" : "添加失败";
            return isSuccess;

        }
        #endregion

        #region 分页获取(GetCommodityInfoDTOs)
        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="page">第几页</param>
        /// <param name="limit">每页几条数据</param>
        /// <param name="commodityName">名称模糊查询条件</param>
        /// <param name="count">数据总数</param>
        /// <returns></returns>
        public List<GetCommodityInfoDTO> GetCommodityInfoList(int page, int limit, string commodityName, out int count)
        {
            //linq方法
            var data = from c in _unmanContexts.CommodityInfo.Where(c => !c.IsDalete)
                       join x in _unmanContexts.ProductType.Where(x => !x.IsDalete)
                       on c.Product_TypeId equals x.Id
                       into TempDX
                       from cc2 in TempDX.DefaultIfEmpty()
                       select new GetCommodityInfoDTO
                       {
                           Id = c.Id,//主键
                           Description = c.Description,//描述
                           Specification = c.Specification,//商品规格
                           CommodityName = c.CommodityName,//商品名称
                           ImgUrl = c.ImgUrl,//商品图片
                           Num = c.Num,//库存数量
                           Unit = c.Unit,//单位
                           Money = c.Money,//价格
                           WarningNum = c.WarningNum,//库存警告
                           CreateTime = c.CreateTime,//创建时间
                           Product_TypeId = c.Product_TypeId,//商品类型

                           Product_TypeName = cc2.Product_TypeName,
                       };
            //名称不能为空时拼接查询参数
            if (!string.IsNullOrWhiteSpace(commodityName))
            {
                data = data.Where(c => c.CommodityName.Contains(commodityName));
            }
            //求总数
            count = data.Count();
            //分页
            var listPage = data.OrderByDescending(d => d.CreateTime).Skip(limit * (page - 1)).Take(limit).ToList();
            //返回结果
            return listPage;

        }
        #endregion

        #region 返回商品类别的商品名称(GetSelectOptions)
        public object GetSelectOptions()
        {
            //查询商品信息
            var parentSelect = _unmanContexts.ProductType.Where(c => !c.IsDalete)
                                                            .Select(c => new
                                                            {
                                                                value = c.Id,
                                                                title = c.Product_TypeName,
                                                            }).ToList();

            var data = new
            {
                parentSelect,
            };
            return data;


        }

        #endregion

        #region 编辑(UpdateCommodityInfo)
        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="commodityInfo"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool UpdateCommodityInfo(CommodityInfo commodityInfo, out string msg)
        {
            if (string.IsNullOrWhiteSpace(commodityInfo.Id))
            {
                msg = "id不能为空";
                return false;
            }
            if (string.IsNullOrWhiteSpace(commodityInfo.CommodityName))
            {
                msg = "商品名称不能为空";
                return false;
            }

            //查询旧数据
            CommodityInfo oldEntity = _commodityInfoDAL.GetEntityById(commodityInfo.Id);
            if (oldEntity == null)
            {
                msg = "不存在";
                return false;
            }
            //判断商品名称是否有修改
            if (oldEntity.CommodityName != commodityInfo.CommodityName)
            {
                //查找数据是否已经有该名字
                var entity = _commodityInfoDAL.GetEntities().FirstOrDefault(c => c.CommodityName == commodityInfo.CommodityName);
                if (entity != null)
                {
                    msg = "商品类别名称重复";
                    return false;
                }
            }
            //赋值
            oldEntity.CommodityName = commodityInfo.CommodityName;
            oldEntity.Description = commodityInfo.Description;
            oldEntity.Product_TypeId = commodityInfo.Product_TypeId;
            oldEntity.Specification = commodityInfo.Specification;
            oldEntity.Num = commodityInfo.Num;
            oldEntity.Unit = commodityInfo.Unit;
            oldEntity.Money = commodityInfo.Money;
            oldEntity.WarningNum = commodityInfo.WarningNum;
            oldEntity.ImgUrl = commodityInfo.ImgUrl;

            bool isSuccess = _commodityInfoDAL.UpdateEntity(oldEntity);//更新商品到数据库
            msg = isSuccess ? "更新成功！" : "更新失败!";//返回消息
            return isSuccess;

        }
        #endregion

        #region 软删除(DeleteCommodityInfo)
        public bool DeleteCommodityInfo(string id)
        {
            //根据id查是否存在
            CommodityInfo commodityInfo = _commodityInfoDAL.GetEntityById(id);
            if (commodityInfo == null)
            {
                return false;
            }

            //修改用户的状态
            commodityInfo.IsDalete = true;
            commodityInfo.DeleteTime = DateTime.Now;
            //返回结果
            return _commodityInfoDAL.UpdateEntity(commodityInfo);

        }
        #endregion

        //#region 批量删除(DeleteCommodityInfos)
        //public bool DeleteCommodityInfos(List<string> ids)
        //{
        //    foreach (var id in ids)
        //    {
        //        //根据id查询
        //        CommodityInfo commodityInfo = _commodityInfoDAL.GetEntityById(id);
        //        if (commodityInfo == null)
        //        {
        //            continue;//跳出本次循环
        //        }
        //        commodityInfo.IsDalete = true;
        //        commodityInfo.DeleteTime = DateTime.Now;
        //    }
        //    return true;
        //}
        //#endregion

        #region 上传Excel入库(Upload)
        public bool Upload(Stream stream, string extension, string userId, out string msg)
        {

            //NOPI库
            //创建一个工作室
            IWorkbook wk = null;
            //判断Excel版本
            if (extension.Equals(".xls"))//2003
            {
                //文件流写入工作簿
                wk = new HSSFWorkbook(stream);
            }
            else
            {
                wk = new XSSFWorkbook(stream);
            }

            stream.Close();//关闭资源
            stream.Dispose();//释放资源

            //获取第一个Sheet
            ISheet sheet = wk.GetSheetAt(0);//索引从0开始
            //先获取sheet有多少行
            int rowNum = sheet.LastRowNum;

            //打开事务
            using (var transaction = _unmanContexts.Database.BeginTransaction())
            {
                try
                {
                    for (int i = 1; i <= rowNum; i++)
                    {
                        IRow row = sheet.GetRow(i);//遍历获取每一行

                        ICell cell = row.GetCell(0);//每一行的第一列
                        string value = cell.ToString();//获取到的值为商品名称

                        ICell cell2 = row.GetCell(2);//获取每一行的第三列
                        string value2 = cell2.ToString();//实际购买数量


                        int num;
                        bool b = int.TryParse(value2, out num);
                        if (b == false)
                        {
                            transaction.Rollback();//事务回滚
                            msg = $"第{i + 1}行商品的实际购买数量有误";
                            return false;
                        }
                        //查该商品存在数据库中的数据
                        CommodityInfo commodityInfo = _commodityInfoDAL.GetEntities().FirstOrDefault(x => x.IsDalete == false && x.CommodityName == value);
                        if (commodityInfo == null)
                        {
                            transaction.Rollback();//事务回滚
                            msg = $"第{i + 1}行商品不存在！{value}";
                            return false;
                        }
                        //实例化入库记录
                        ProductRecord productRecord = new ProductRecord()
                        {
                            Id = Guid.NewGuid().ToString(),
                            ConsumableId = commodityInfo.Id,//耗材Id
                            CreateTime = DateTime.Now,//创建时间
                            Creator = userId,//添加人的Id
                            Num = num,//数量
                            Type = (int)CommodityInfoRecordTypeEnums.入库,
                        };
                        //添加到商品记录表的数据库
                        _unmanContexts.ProductRecord.Add(productRecord);//添加到商品记录，没有提交到数据库
                        bool isOk = _unmanContexts.SaveChanges() > 0;//执行提交到数据库
                        if (isOk == false)
                        {
                            transaction.Rollback();//事务回滚
                            msg = $"第{i + 1}行商品记录添加失败";
                            return false;
                        }
                        //更新商品信息库存
                        commodityInfo.Num += num;

                        isOk = _commodityInfoDAL.UpdateEntity(commodityInfo);

                        if (isOk == false)
                        {
                            transaction.Rollback();//事务回滚
                            msg = $"第{i + 1}行商品信息更新失败{value}";
                            return false;
                        }
                    }
                    //根据行数遍历
                    //提交事务
                    transaction.Commit();
                    msg = "入库成功";
                    return true;
                }
                catch (Exception ex)
                {
                    transaction.Rollback();//报错回滚事务
                    msg = ex.Message;
                    return false;
                }
            }
        }
        #endregion

        #region 获取类别分类(Getcon)
        public List<ProductType> Getcon()
        {
            var list = _unmanContexts.ProductType.Where(x => !x.IsDalete);
            return list.ToList();
        }
        #endregion

        #region Exce导出出库记录的方法(GetDowload)
        public Stream GetDowload(out string dowloadFileName, string staffName)
        {


            var datas = (from pr in _unmanContexts.ProductRecord
                         join c in _unmanContexts.CommodityInfo.Where(x => x.IsDalete == false)
                         on pr.ConsumableId equals c.Id//商品记录表的耗材id 等于商品信息表的id
                         into tempPRC
                         from cc in tempPRC.DefaultIfEmpty()

                         join s in _unmanContexts.StaffInfo//链商店用工表
                         on pr.Creator equals s.Id//商品记录的操作人的id
                         into tempSRP
                         from ss in tempSRP.DefaultIfEmpty()
                         select new
                         {
                             cc.CommodityName,//商品名称
                             cc.Specification,//商品规格
                             Type = pr.Type == (int)CommodityInfoRecordTypeEnums.入库 ? "入库" : "出库",//出入库类型
                             pr.Num,//每次出入库的数量
                             pr.CreateTime,//创建时间
                             staffName,
                         }).ToList();

            //开始对文件进行操作
            string path = Directory.GetCurrentDirectory();
            string fileName = "出库记录" + DateTime.Now.ToString("yyyy-MM-dd hh mm ss") + ".xlsx";//出入库记录导出2023-08-22 11 11 10.xlsx
            //拼接完整的路径
            string filePath = Path.Combine(path, fileName);

            //创建一个Excel对象
            IWorkbook wk = null;
            //获取文件的扩展名
            string extension = Path.GetExtension(filePath);

            //操作文件
            using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
            {
                //根据Excel 后缀判断版本，实例化不同对象
                if (extension.Equals(".xls"))
                {
                    wk = new HSSFWorkbook();
                }
                else
                {
                    wk = new XSSFWorkbook();
                }
                //先创一个sheet表
                ISheet sheet = wk.CreateSheet("sheet1");

                #region 创建表头
                IRow row = sheet.CreateRow(0);
                string[] title =
                {
                    "商品耗材名称",
                    "商品耗材规格",
                    "出入库类型",
                    "出入库数量",
                    "出入库时间",
                    "操作人"
                };
                for (int i = 0; i < title.Length; i++)
                {
                    ICell cell = row.CreateCell(i);//第1列
                    cell.SetCellValue(title[i]);//给第1列赋值
                }
                #endregion

                #region 主体部分
                for (int i = 0; i < datas.Count; i++)
                {
                    var data = datas[i];//获取数据
                    //创建行
                    IRow tempRow = sheet.CreateRow(i + 1);
                    //创列
                    ICell tempCell = tempRow.CreateCell(0);//每一行的第1列
                    tempCell.SetCellValue(data.CommodityName);

                    ICell tempCell2 = tempRow.CreateCell(1);//每一行的第2列
                    tempCell2.SetCellValue(data.Specification);

                    ICell tempCell3 = tempRow.CreateCell(2);//每一行的第3列
                    tempCell3.SetCellValue(data.Type);

                    ICell tempCell4 = tempRow.CreateCell(3);//每一行的第4列
                    tempCell4.SetCellValue(data.Num);

                    ICell tempCell5 = tempRow.CreateCell(4);//每一行的第5列
                    tempCell5.SetCellValue(data.CreateTime.ToString("yyyy-MM-dd hh:mm:ss"));

                    ICell tempCell6 = tempRow.CreateCell(5);//每一行的第6列
                    tempCell6.SetCellValue(data.staffName);
                }
                #endregion
                //把excel写到文件里
                wk.Write(fs);
                //重新打开
                FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);

                dowloadFileName = fileName;//文件名
                return fileStream;
            }
        }
        #endregion

        #region 购买
        public bool Purchase(string userId, string userName, string productId, out string msg)
        {
            using (var transtion = _unmanContexts.Database.BeginTransaction())
            {
                try
                {
                    //判断当前用户id是否已经登录了
                    if (userId == null)
                    {
                        msg = "还没有登录";
                        return false;
                    }

                    //接收前台传过来的数据
                    UserBalanceInfo userBalanceInfo = _unmanContexts.UserBalanceInfo.FirstOrDefault(u => u.UserId == userId);
                    CommodityInfo commodityInfo = _unmanContexts.CommodityInfo.FirstOrDefault(c => c.Id == productId);
                    if (userBalanceInfo.Userbalance < commodityInfo.Money)
                    {
                        transtion.Rollback();
                        msg = "余额不足";
                        return false;
                    }
                    if (commodityInfo.Num == 0)
                    {
                        transtion.Rollback();
                        msg = "已售空";
                        return false;
                    }

                    if (commodityInfo.Num <= 0)
                    {
                        transtion.Rollback();
                        msg = "已售空";
                        return false;
                    }
                    //库存数量减1
                    commodityInfo.Num -= 1;

                   

                    //生成订单

                    OrderInfo order = new OrderInfo()
                    {
                        Id = Guid.NewGuid().ToString(),
                        CreateTime = DateTime.Now,//创建时间
                        ProductId = commodityInfo.Id,
                        Description = commodityInfo.Description,//描述
                        UserId = userId,//用户id
                        UserName = userName,//用户名
                        Money = commodityInfo.Money,//价格
                        IsDalete = false,
                    };
                    bool IsSuccess = _orderInfoDAL.CreateEntity(order);
                    if (!IsSuccess)
                    {
                        transtion.Rollback();
                        msg = "添加订单失败";
                        return false;
                    }
                    //扣去用户余额
                    userBalanceInfo.Userbalance -= commodityInfo.Money;
                    _unmanContexts.UserBalanceInfo.Update(userBalanceInfo);

                    //实例化出库记录
                    ProductRecord productRecord = new ProductRecord()
                    {
                        Id = Guid.NewGuid().ToString(),
                        ConsumableId = commodityInfo.Id,//耗材Id
                        CreateTime = DateTime.Now,//创建时间
                        Creator = userId,//添加人的Id
                        Num = commodityInfo.Num,//数量
                        Type = (int)CommodityInfoRecordTypeEnums.出库,
                    };
                    //添加到商品记录表的数据库
                    _unmanContexts.ProductRecord.Add(productRecord);//添加到商品记录，没有提交到数据库
                    bool isOk = _unmanContexts.SaveChanges() > 0;//执行提交到数据库

                    //更新商品信息库存
                    commodityInfo.Num += productRecord.Num;

                    //IsSuccess = _unmanContexts.SaveChanges() > 0;
                    //if (!IsSuccess)
                    //{
                    //    transtion.Rollback();
                    //    msg = "用户更新失败";
                    //    return false;
                    //}




                    //生产交易记录
                    OrderDetaIls orderDetaIls = new OrderDetaIls()
                    {
                        Id = Guid.NewGuid().ToString(),
                        ProductId = order.ProductId,//商品id
                        OrderInfoId = order.Id,//订单id
                        CreateTime = DateTime.Now,//创建时间
                        Description = commodityInfo.Description,//描述
                        CommodityName = commodityInfo.CommodityName,//商品名称
                    };
                    _unmanContexts.OrderDetaIls.Add(orderDetaIls);


                    IsSuccess = _unmanContexts.SaveChanges() > 0;

                    if (!IsSuccess)
                    {
                        transtion.Rollback();
                        msg = "添加交易记录失败";
                        return false;
                    }



                    transtion.Commit();
                    msg = "购买成功";
                    return true;
                }
                catch (Exception ex)
                {

                    transtion.Rollback();
                    msg = ex.Message;
                    return false;
                }
            }

        }
        #endregion

    }
}
